//
// Created by ta&to on 2022/8/25.
//

#include <sys/unistd.h>
#include <sys/stat.h>
#include "tcp_log.h"

ssize_t write_fd(int console, void *buf, size_t size)
{
    return write(console, buf, size);
}
ssize_t write_file(file_n *file, void *buf, size_t size, off_t  offset)
{
    ssize_t fsize = fputs(buf,file->fd);
    fflush(file->fd);
    return fsize;
}

char *pwd()
{
    char *path = (char *) tcp_malloc(FILENAME_MAX);
    return getcwd(path, FILENAME_MAX);
}
/**
 * 文件是否存在
 * @param filename
 * @return
 */
int isExist(char *filename)
{
    int err;
    if(ISNULL(filename)) return 0;
    err = access(filename, F_OK);
    if(err == 0) return 1;
    else return 0;

}
int canR(char *filename)
{
    int err;
    if(isExist(filename))
    {
        err = access(filename, R_OK);
        if(err == 0) return 1;
        else return 0;
    }
    return 0;
}
int canW(char *filename)
{
    int err;
    if(isExist(filename))
    {
        err = access(filename, W_OK);
        if(err == 0) return 1;
        else return 0;
    }
    return 0;
}
int canX(char *filename)
{
    int err;
    if(isExist(filename))
    {
        err = access(filename, X_OK);
        if(err == 0) return 1;
        else return 0;
    }
    return 0;
}
/**
 * 判断是否是相对路径
 * @param path
 * @return 0、否 1、是
 */
isRelative(char *path)
{
    if(path[0] == '.' && path[1] == '/' || (path[0] == '.' && path[1] == '.' && path[2] == '/'))
        return 1;
    return 0;
}
static inline int mkdir_(char *file)
{
    if(ISNULL(file)) return 0;
#if defined(__WIN32__) || defined(__WIN64__) || defined(__MINGW32__)
    mkdir(file);
#else
    mkdir(file, 0755);
#endif
}
/***
 * 将重复的字符归一
 * @param str
 * @param dot 需要归一的字符
 * @param ignore 忽略的字符
 * @param i_num  忽略次数
 * @return
 */
char* toOne(char *str, char dot, char *ignore, int i_num)
{
    unsigned long size = strlen(str);
    int i_size = strlen(ignore);
    char *buf = (char *) tcp_calloc(FILENAME_MAX);
    int b_flag = 0;
    int bp = 0, ip = 0;
    for (int i = 0; i < size; ++i) {
        if(i_num != 0 && ip == 0 && !memcmp(&str[i], ignore, i_size))
        {
            ip = i_size;
            i_num--;
        }
        if(ip == 0)
            if(str[i] == dot){
                if(b_flag == 1) continue;
                b_flag = 1;
            }
            else b_flag = 0;
        else ip--;
        buf[bp++] = str[i];
    }
    return buf;
}
/**
 * 格式化文件地址
 * @param input
 * @return
 */
char* getAbsolutePath(char* input){
    int i;
    unsigned long size = strlen(input);
    char buff[strlen(input)];
    int buffIndex = 0;
    unsigned char pos[strlen(input)];
    int sigNum = 0;
    for(i=0;i<size;i++){
        if ((i+2)<size && input[i] == '.' && input[i+1] == '.' && input[i+2] == '/') {
            buffIndex = pos[sigNum - 2] + 1;
            sigNum--;
            i = i+2;
            continue;
        }
        if((i+1)<size && input[i] == '.' && input[i+1] == '/')
        {
            continue;
        }
        buff[buffIndex++] = input[i];
    }

    buff[buffIndex] = 0;
    return toOne(buff, '/', "://", 1);
}
/**
 * 循环创建文件
 * @param path
 * @return
 */
int mkdirs(char *path)				//创建目录
{
    int len = strlen(path);
    char pathname[FILENAME_MAX];			//用于存储上级目录
    memset(pathname,0,sizeof(pathname));

    while(path[len] != '/')
    {
        len--;
    }

    strncpy(pathname,path,len);		//存储上级目录

    if(isExist(pathname))	//若上级目录已存在
    {
        int i=0;
        mkdir_(path);		//创建目标目录
    }
    else
    {
        mkdirs(pathname);		//递归创建上级目录
        mkdir_(path);		//创建上级目录后创建目标目录
    }
}


static inline FILE *openfile(char *path, char* filename, char *type, enum path_type pt)
{
    char file[FILENAME_MAX];
    memset(&file,0, FILENAME_MAX);
    switch (pt) {
        case absolutely:                        // 绝对路径
            memcpy(file, path, strlen(path));
            break;

        case relative:                          //相对路径
        {
            char *current = pwd();
            memcpy(file, current, strlen(current));
            memcpy(&file[strlen(current)], "/", 1);
            memcpy(&file[strlen(current)+1], path, strlen(path));
            if(ISNULL(current))free(current);
            current = NULL;
            break;
        }
    }

    tcp_amemcpy(file, getAbsolutePath(file));
    mkdirs(&file);
    memcpy(file+strlen(file), "/", 1);
    int l = strlen(filename);
    int s = strlen(file);
    memcpy(file+s, filename, l);
    return fopen(file, type);
}

static inline FILE *openfw(char *path, char *type)
{
    char *filename = (char*) tcp_calloc(FILENAME_MAX);
    char *t_path = (char*) tcp_calloc(strlen(path));
    int len,offlen;

    offlen = len = strlen(path);
    while(path[offlen] != '/' && (path[offlen] != '\\' && path[offlen-1] != '\\' ))
    {
        offlen--;
    }
    memcpy(filename, &path[offlen+1], len - (offlen+1));
    memcpy(t_path, path, offlen);
    if(isRelative(t_path))
        return openfile(t_path, filename, type, relative);
    return openfile(t_path, filename,  type, absolutely);
}

FILE *wfile(char *file)
{
    FILE *file_ = openfw(file,"ab+");
    if(ISNULL(file_))
    {
        char innerfile[FILENAME_MAX];
        if(!isRelative(file))
            memcpy(innerfile, file, strlen(file));

        else {
            char *current = pwd();
            memcpy(innerfile, current, strlen(current));
            memcpy(&innerfile[strlen(current)], "/", 1);
            memcpy(&innerfile[strlen(current)+1], file, strlen(file));
            if(ISNULL(current))free(current);
            current = NULL;
        }
        tcp_amemcpy(innerfile, getAbsolutePath(innerfile));
        printf(stderr, "open path is fail :%s maybe you don't have permission!\n", innerfile);
    }
    return file_;
}